package org.example.framework.util;

public final class HashUtil {
    private static final long SEED = 2862933555777941757L;
    private static final double FACTOR = 0x1.0p31;

    private HashUtil() {
    }

    /**
     * 一致性哈希, 计算在哈希环中的唯一位置.
     *
     * @param input   hashCode
     * @param buckets 哈希环
     * @return 哈希环中的位置
     */
    public static int consistentHash(long input, int buckets) {
        LinearCongruentialGenerator generator = new LinearCongruentialGenerator(input);
        int candidate = 0;
        int next;
        while (true) {
            next = (int) ((candidate + 1) / generator.nextDouble());
            if (next >= 0 && next < buckets) {
                candidate = next;
            } else {
                return candidate;
            }
        }
    }

    private static final class LinearCongruentialGenerator {
        private long state;

        LinearCongruentialGenerator(long seed) {
            this.state = seed;
        }

        double nextDouble() {
            state = SEED * state + 1;
            return ((double) ((int) (state >>> 33) + 1)) / FACTOR;
        }
    }
}
